package com.kehutong.charge.service.impl;

import com.kehutong.charge.util.enums.*;
import com.kehutong.charge.vo.ChargeBillCommunityExcelVO;
import com.kehutong.charge.entity.*;
import com.kehutong.charge.service.ChargeBillManageService;
import com.kehutong.charge.service.CommonService;
import com.kehutong.charge.service.PayManagesService;
import com.kehutong.charge.service.ReceiptOrdersService;
import com.kehutong.charge.util.CommonClient;
import com.kehutong.charge.util.CommonUtil;
import com.kehutong.charge.util.PdfTableUtil;
import com.kehutong.charge.util.PdfUtil;
import com.kehutong.common.DailyUtil;
import com.kehutong.common.DoveClient;
import com.kehutong.common.Java8TimeUtils;
import com.kehutong.common.errcode.Assert;
import com.kehutong.common.excel.tool.ExcelTool;
import com.kehutong.common.urlconfig.FileUrlConfig;
import com.kehutong.common.util.ListUtils;
import com.kehutong.common.util.Token;
import org.coraframework.bean.Beans;
import org.coraframework.converter.util.StringUtil;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.result.Result;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.util.Objects;
import org.coraframework.util.time.TimeUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @program: kht
 * @description: ChargeBillManageServiceImpl
 * @author: joneron
 * @create: 2021/7/5
 **/
public class ChargeBillManageServiceImpl implements ChargeBillManageService {

    private static final Logger logger = LoggerFactory.getLogger(ChargeBillManageServiceImpl.class);

    @Inject
    private JdbcSession jdbcSession;
    @Inject
    CommonClient commonClient;
    @Inject
    CommonService commonService;
    @Inject
    ExcelTool excelTool;
    @Inject
    private DoveClient doveClient;
    @Inject
    private FileUrlConfig fileUrlConfig;
    @Inject
    ReceiptOrdersService receiptOrderService;
    @Inject
    PayManagesService payManagesService;



    @Override
    public Page<ChargeBillCommunity> findPage(JSONObject jsonObject) {
        FindPage<ChargeBillCommunity> find = jdbcSession.findPage(ChargeBillCommunity.class)
                .eq("deleted", false)
                .eq(jsonObject,"communityNo")
                .eq(jsonObject,"feeType")
                .eq(jsonObject,"billStatus")
                .eq(jsonObject,"billYearMonth")
                .like(jsonObject,"communityBillNo")
                .order("createTime", "desc");

        find.page(jsonObject);
        return find.exe();
    }


    @Override
    public void pageExport(HttpServletRequest req, HttpServletResponse resp, JSONObject jsonObject) {
        jsonObject.put("pageNo", 1);
        jsonObject.put("pageSize", Short.MAX_VALUE);
        List<ChargeBillCommunity> list = findPage(jsonObject).getList();
        Assert.notEmpty(list,"没有找到常规账单的相关待导出数据.");
        List<ChargeBillCommunityExcelVO> dtoList = ListUtils.copyBeanList(list, ChargeBillCommunityExcelVO::new);
        excelTool.excelDownload(req,resp,dtoList,"常规账单列表导出");
    }



    @Override
    public List<ChargeBillCommunity> findList(JSONObject jsonObject) {
        return jdbcSession.findArray(ChargeBillCommunity.class)
                .eq("deleted", false)
                .eq(jsonObject,"communityNo")
                .eq(jsonObject,"billStatus")
                .eq(jsonObject,"billYearMonth")
                .exe();
    }

    @Override
    public Object save(ChargeBillCommunity chargeBillManage) throws Exception {

        //判断是否已经生成账单
        List<ChargeBillCommunity> communityList = jdbcSession.findArray(ChargeBillCommunity.class)
                .eq("communityNo",chargeBillManage.getCommunityNo())
                .eq("billYearMonth",chargeBillManage.getBillYearMonth())
                .noEq("billStatus",ChargeBillStatusEnum.BILL_PAID_CLOSE).exe();
        if(null != communityList && communityList.size() > 0){
            return Result.error(2021, "该小区账单已经生成！");
        }

        /**
         * 生成账单
         */
        return generateCommunityBill(chargeBillManage);
    }

    @Override
    public Object resetCommunityBill(JSONObject jsonObject, Token token) throws Exception {

        String communityBillNo = jsonObject.getString("communityBillNo");

        //1、根据账单号查询账单
        List<ChargeBillCommunity> chargeBillCommunityList = jdbcSession.findArray(ChargeBillCommunity.class)
                .eq("communityBillNo",communityBillNo)
                .eq("billStatus",ChargeBillStatusEnum.BILL_PAID_CLOSE)
                .order("createTime","desc").exe();
        if(null == chargeBillCommunityList || chargeBillCommunityList.size() == 0){
            return Result.error(2021, "小区需作废才能重新生成！");
        }

        //重新复制
        ChargeBillCommunity oldCommunity =chargeBillCommunityList.get(0);

        //2、根据账单号查询账单
        List<ChargeBillCommunity> chargeBillCommunity2= jdbcSession.findArray(ChargeBillCommunity.class)
                .eq("communityNo",oldCommunity.getCommunityNo())
                .eq("billYearMonth",oldCommunity.getBillYearMonth())
                .noEq("billStatus",ChargeBillStatusEnum.BILL_PAID_CLOSE).exe();
        if(chargeBillCommunity2.size() > 0){
            return Result.error(2021, "小区账单已经存在！");
        }



        ChargeBillCommunity chargeBillCommunity = Pool.newInstance(ChargeBillCommunity.class);
        Beans.from(oldCommunity).to(chargeBillCommunity).exclude("id").igornNull().copy();

        //2、先判断类目账单是否有缴费状态
        List<ChargeBillItems> billItems = jdbcSession.findArray(ChargeBillItems.class)
                .eq("communityNo",chargeBillCommunity.getCommunityNo())
                .eq("billYearMonth",chargeBillCommunity.getBillYearMonth())
                .noEq("billStatus",ChargeBillStatusEnum.BILL_WAIT_PAID)
                .noEq("billStatus",ChargeBillStatusEnum.BILL_PAID_CLOSE).exe();
        //3、有缴费状态则不能重新生成账单
        if(null != billItems && billItems.size() > 0 ){
            return Result.error(2021, "该小区已经有缴费，不能重新生成账单！");
        }
        //4、所有类目单项作废
        for (int i = 0; i < billItems.size(); i++) {
            ChargeBillItems items = billItems.get(i);
            items.setBillStatus(ChargeBillStatusEnum.BILL_PAID_CLOSE);
            items.setUpdateTime(TimeUtil.timestamp());
            items.setUpdateName(token.getUsername());
            jdbcSession.updateById(items);
        }
        //5、所有房屋账单作废
        List<ChargeBillHouse> houseList = jdbcSession.findArray(ChargeBillHouse.class)
                .eq("communityBillNo",communityBillNo)
                .eq("billYearMonth",chargeBillCommunity.getBillYearMonth()).exe();
        for (int i = 0; i < houseList.size(); i++) {
            ChargeBillHouse house = houseList.get(i);
            house.setBillStatus(ChargeBillStatusEnum.BILL_PAID_CLOSE);
            house.setUpdateTime(TimeUtil.timestamp());
            house.setUpdateName(token.getUsername());
            jdbcSession.updateById(house);
        }

        //6、小区账单作废
        chargeBillCommunity.setBillStatus(ChargeBillStatusEnum.BILL_PAID_CLOSE);
        chargeBillCommunity.setUpdateTime(TimeUtil.timestamp());
        chargeBillCommunity.setUpdateName(token.getUsername());
        jdbcSession.updateById(chargeBillCommunity); //小区账单作废

        /**
         * 7、重新生成账单
         */
        return generateCommunityBill(chargeBillCommunity);
    }

    @Override
    public Object generateItemBill(ChargeBillCommunity entity) throws Exception {

        //1、先判断类目账单是否有缴费状态
        List<ChargeBillItems> billItems = jdbcSession.findArray(ChargeBillItems.class)
                .eq("communityNo",entity.getCommunityNo())
                .eq("billYearMonth",entity.getBillYearMonth())
                .eq("meterTypeNo",entity.getOperaDesc())
                .noEq("billStatus",ChargeBillStatusEnum.BILL_WAIT_PAID)
                .noEq("billStatus",ChargeBillStatusEnum.BILL_PAID_CLOSE).exe();
        //2、有缴费状态则不能重新生成账单
        if(null != billItems && billItems.size() > 0 ){
            return Result.error(2021, "该小区已经有缴费，不能重新生成账单！");
        }

        //3、重新生成类目账单
        return generateCommunityBill(entity);
    }

    /**
     * 生成账单
     * @param chargeBillManage
     * @return
     * @throws Exception
     */
    private Object generateCommunityBill(ChargeBillCommunity chargeBillManage) throws Exception {

        //1、根据所选择的小区，生成该小区所有房屋账单
        String communityNo = chargeBillManage.getCommunityNo();

        Map<String, JSONObject> result = commonClient.getHouseMap(communityNo);

        if (null == result) {
            logger.warn("小区：{},改小区下面没有房屋！", communityNo);
            return Result.error(2021, "改小区下面没有房屋！");
        }
        //小区账单编号
        String communityBillNo = CommonUtil.generateRandom("XQ");
        chargeBillManage.setCommunityBillNo(communityBillNo);
        BigDecimal amountComm = BigDecimal.ZERO;
        int num = 0 ; //累计生成房屋条数

        for(JSONObject json:result.values()){

            String houseNo = json.getString("id");

            //1、根据房屋id查询费用配置绑定项,可能配置多次
            ChargeHouseConfig houseConfig = jdbcSession.findOne(ChargeHouseConfig.class)
                    .eq("houseNo",houseNo)
                    .exe();
            if(null == houseConfig){
                logger.warn("房屋：{},没有设置收费项目！",houseNo);
                continue;
            }

            List<ChargeHouseSet> houseSetList = jdbcSession.findArray(ChargeHouseSet.class)
                    .eq("chargeHouseNo",houseConfig.getId())
                    .exe();

            if(null == houseSetList || 0 == houseSetList.size()){
                logger.warn("房屋：{},没有设置收费项目！",houseNo);
                continue;
            }

            //2、创建房屋账单
            ChargeBillHouse chargeBillHouse = Pool.newInstance(ChargeBillHouse.class);
            chargeBillHouse.setHouseBillNo(CommonUtil.generateRandom("FW"));
            chargeBillHouse.setChargeName(houseConfig.getChargeName());
            chargeBillHouse.setResidentsType(houseConfig.getReType());
            chargeBillHouse.setBillYearMonth(chargeBillManage.getBillYearMonth());
            chargeBillHouse.setUserNo(houseConfig.getOwnerNo());
            chargeBillHouse.setHouseNo(houseNo);
            BigDecimal amountHouse = BigDecimal.ZERO;

            for (int i = 0; i < houseSetList.size(); i++) {
                //3、根据费用配置项id查询具体配置信息，并计算费用
                ChargeHouseSet chs = houseSetList.get(i);

                //4、查询费用配置参数
                ChargeProjectConfig pconfig = jdbcSession.findById(ChargeProjectConfig.class,chs.getProjectFeeNo());

                //5、查询仪表类型
                ChargeTypeConfig typeConfig = jdbcSession.findById(ChargeTypeConfig.class,pconfig.getFeeTypeNo());

                //6、根据房屋和类型、月份、周期、查询抄表使用量(有多次抄表的情况)
                List<MeterReading> meterReading = jdbcSession.findArray(MeterReading.class)
                        .eq("houseNo",chs.getHouseNo())
                        .eq("meterTypeNo",typeConfig.getMeterTypeNo())
                        .like("endTime",chargeBillManage.getBillYearMonth())
                        .exe();

                if(null == meterReading || meterReading.size() == 0){
                    logger.warn("房间：{},在{}没有抄表数据！",chs.getHouseNo(),chargeBillManage.getBillYearMonth());
                    continue;
                }
                num += 1;
                for (int j = 0; j < meterReading.size(); j++) {

                    MeterReading reading = meterReading.get(j);
                    ChargeBillItems items = Pool.newInstance(ChargeBillItems.class);
                    String billNO = CommonUtil.generateRandom("FJ");
                    items.setItemBillNo(billNO);
                    items.setBillStatus(ChargeBillStatusEnum.BILL_WAIT_PAID);
                    //7、计算单个类型的总费用
                    BigDecimal amount = commonService.calcFeeCommon(pconfig,reading.getTimeUseNumber(),billNO);
                    amount = amount.setScale(2,BigDecimal.ROUND_UP); //保存两位小数,只入不舍
                    amountHouse = amountHouse.add(amount);
                    items.setBillAmount(amount);
                    items.setFeeTypeName(typeConfig.getFeeTypeName());
                    items.setFeeTypeNo(typeConfig.getId());
                    items.setChargeName(houseConfig.getChargeName());
                    items.setUserNo(houseConfig.getOwnerNo());
                    items.setResidentsType(houseConfig.getReType());
                    items.setCreateName(chargeBillManage.getCreateName());
                    items.setBillCycleStart(chargeBillManage.getBillCycleStart());
                    items.setBillCycleEnd(chargeBillManage.getBillCycleEnd());
                    items.setBillDate(chargeBillManage.getBillDate());
                    items.setChargeDate(chargeBillManage.getChargeDate());
                    items.setDepartmentNo(chargeBillManage.getDepartmentNo());
                    items.setDepartmentName(chargeBillManage.getDepartmentName());
                    items.setDepartmentNos(chargeBillManage.getDepartmentNos());
                    items.setCommunityNo(reading.getCommunityNo());
                    items.setCommunityName(reading.getCommunityName());
                    items.setCommunityBillNo(chargeBillManage.getCommunityBillNo());
                    items.setHouseNo(chs.getHouseNo());
                    items.setHouseBillNo(chargeBillHouse.getHouseBillNo());
                    items.setMeterTypeNo(reading.getMeterTypeNo());
                    items.setMeterTypeName(reading.getMeterTypeName());
                    items.setMeterClassifyName(reading.getMeterClassifyName());
                    items.setMeterClassifyNo(reading.getMeterClassifyNo());
                    items.setBillYearMonth(chargeBillHouse.getBillYearMonth());
                    items.setUsageNumber(reading.getTimeUseNumber());
                    items.setBillAddress(reading.getMeterAddress());

                    //返回天数
                    items.setPenaltyDays(Java8TimeUtils.subDate(chargeBillManage.getPenaltyDate()));
                    items.setPenaltyAmount(new BigDecimal(0));
                    items.setPenaltyDate(chargeBillManage.getPenaltyDate());
                    items.setCalcUnit(reading.getCalcUnit());
                    items.setPayableAmount(amount);
                    items.setPrice(pconfig.getPrice());
                    items.setLastTimeNumber(reading.getLastTimeNumber());
                    items.setTimeNumber(reading.getTimeNumber());
                    items.setStartTime(reading.getStartTime());
                    items.setEndTime(reading.getEndTime());

                    //8、记录费用项
                    jdbcSession.insert(items);
                }
            }

            amountComm = amountComm.add(amountHouse);
            chargeBillHouse.setBillAmount(amountHouse);
            chargeBillHouse.setBillAmountUnPaid(amountHouse);

            //a大于b, 否则就是没有抄表信息
            if(amountHouse.compareTo(BigDecimal.ZERO) == 1){
                //9、添加房屋账单
                insetHouseBill(chargeBillManage,chargeBillHouse,json);
            }
        }

        //a大于b, 否则就是没有抄表信息
        if(amountComm.compareTo(BigDecimal.ZERO) == 1){
            chargeBillManage.setBillAmountTotal(amountComm);
            chargeBillManage.setBillTotal(num);
            chargeBillManage.setBillStatus(ChargeBillStatusEnum.BILL_WAIT_PAID);
            jdbcSession.insert(chargeBillManage);
        }else {
            return Result.error(2020,"该小区没有设置收费项目或抄表数据！");
        }
        return 0;
    }

    /**
     * 添加房屋账单信息
     * @return
     */
    private Object insetHouseBill(ChargeBillCommunity chargeBillManage,ChargeBillHouse chargeBillHouse,JSONObject json){

        String communityName = json.getString("communityName");
        String buildName = json.getString("buildName");
        String mergeName = json.getString("mergeName");
        String ownerName = json.getString("ownerName");

        String address = communityName + buildName + mergeName;
        chargeBillHouse.setBillAddress(address);
        chargeBillHouse.setChargeName(ownerName);
        chargeBillHouse.setCommunityNo(chargeBillManage.getCommunityNo());
        chargeBillHouse.setCommunityName(communityName);
        chargeBillHouse.setCommunityBillNo(chargeBillManage.getCommunityBillNo());
        chargeBillHouse.setBillStatus(ChargeBillStatusEnum.BILL_WAIT_PAID);
        chargeBillHouse.setBillCycleStart(chargeBillManage.getBillCycleStart());
        chargeBillHouse.setBillCycleEnd(chargeBillManage.getBillCycleEnd());
        chargeBillHouse.setBillDate(chargeBillManage.getBillDate());
        chargeBillHouse.setChargeDate(chargeBillManage.getChargeDate());
        chargeBillHouse.setPenaltyDate(chargeBillManage.getPenaltyDate());
        //计算违约天数,生成账单没有违约
        chargeBillHouse.setPenaltyDays(Java8TimeUtils.subDate(chargeBillManage.getPenaltyDate()));
        chargeBillHouse.setPenaltyAmount(new BigDecimal(0));
        chargeBillHouse.setDepartmentNo(chargeBillManage.getDepartmentNo());
        chargeBillHouse.setDepartmentName(chargeBillManage.getDepartmentName());
        chargeBillHouse.setDepartmentNos(chargeBillManage.getDepartmentNos());
        chargeBillHouse.setCreateName(chargeBillManage.getCreateName());

        return jdbcSession.insert(chargeBillHouse);
    }

    @Override
    public Object update(ChargeBillCommunity chargeBillInterim) {
        return jdbcSession.updateById(chargeBillInterim);
    }

    @Override
    public Object deleteById(String id) {
        ChargeBillCommunity result = Pool.get(ChargeBillCommunity.class, id);
        if (result != null) {
            result.setDeleted(true);
            jdbcSession.updateById(result);
        }
        return Result.success();
    }

    @Override
    public Object cancelCommunityBill(JSONObject jsonObject, Token token) {

        JSONArray jsonArray = jsonObject.getJSONArray("communityBillNos");

        for (int i = 0; i < jsonArray.size(); i++) {

            String billNo = jsonArray.get(i).toString();
            //1、查询对应的小区
            ChargeBillCommunity community = jdbcSession.findOne(ChargeBillCommunity.class).eq("communityBillNo",billNo).exe();

            //2、判断小区下面账单是否有缴费，有缴费则操作失败
            if(ChargeBillStatusEnum.BILL_WAIT_PAID.equals(community.getBillStatus())){

                community.setBillStatus(ChargeBillStatusEnum.BILL_PAID_CLOSE);
                community.setUpdateName(token.getUsername());
                community.setUpdateTime(TimeUtil.timestamp());
                //3、小区数据作废
                jdbcSession.updateById(community);

                //4、房屋数据作废
                List<ChargeBillHouse> billHouses = jdbcSession.findArray(ChargeBillHouse.class).eq(
                        "communityBillNo",community.getCommunityBillNo()).exe();
                for (int j = 0; j < billHouses.size(); j++) {
                    ChargeBillHouse house = billHouses.get(j);
                    house.setBillStatus(ChargeBillStatusEnum.BILL_PAID_CLOSE);
                    house.setUpdateName(token.getUsername());
                    house.setUpdateTime(TimeUtil.timestamp());
                    jdbcSession.updateById(house);

                    //5、类目数据作废
                    List<ChargeBillItems> billItem = jdbcSession.findArray(ChargeBillItems.class).eq(
                            "houseBillNo",house.getHouseBillNo()).exe();
                    for (int b = 0; b < billItem.size(); b++) {
                        ChargeBillItems items = billItem.get(b);
                        items.setBillStatus(ChargeBillStatusEnum.BILL_PAID_CLOSE);
                        items.setUpdateName(token.getUsername());
                        items.setUpdateTime(TimeUtil.timestamp());
                        jdbcSession.updateById(items);
                    }
                }
                commonService.insetLogger(billNo,
                        ChargeLogEnum.LOG_CHARGE_BILL_COM.getDesc(),
                        "小区账单作废",
                        ChargeBillStatusEnum.BILL_PAID_CLOSE.getDesc(),
                        ChargeBillStatusEnum.BILL_WAIT_PAID.getDesc(), "操作成功！", token.getUsername());
            }
        }

        return Result.success();
    }



    /**
     * 费用项
     * @param item
     */
    private void insertItem(ChargeBillItems item){

        item.setItemBillNo(CommonUtil.generateNumber("ZD"));
        item.setBillStatus(ChargeBillStatusEnum.BILL_WAIT_PAID);

        jdbcSession.insert(item);
    }


    public String getOwnerName(String companyNo, String houseNo) throws Exception{
        JSONObject result = doveClient.post("/basic/house/service/get", http->{
            http.addHeader("companyNo", companyNo);
            http.addParam("id", houseNo);
        });
        if (Objects.isNull(result) || Objects.isNull(result.getJSONObject("data"))) {
            return "";
        }
        JSONObject data = result.getJSONObject("data");
        return data.getString("ownerName");
    }


    /**
     * 手动生成收据PDF
     * @param jsonObjects
     * @return
     * @throws Exception
     */
    @Override
    public Object receiptPDFSave(JSONObject jsonObjects, Token token){

        JSONArray jsonArray = jsonObjects.getJSONArray("idList");

        for (int i = 0; i < jsonArray.size(); i++) {

            String orderNo = jsonArray.getString(i);

            //1、根据缴费订单ID查询缴费订单
            ChargeOrderManage order = jdbcSession.findOne(ChargeOrderManage.class).eq("orderNo",orderNo).exe();
            if(Objects.isNull(order)){
                return Result.error(0, "生成收据单失败！没有找到相关的缴费订单");
            }
            logger.info("手动生成收据PDF文件！小区编号：{}",order.getCommunityNo());

            ReceiptManages receiptManage;
            try {
                //2、查询电子签章,判断是否有配置收据模板及公章
                receiptManage = jdbcSession.findOne(ReceiptManages.class)
                        .like("communityList", order.getCommunityNo())
                        .eq("status", true).exe();

                if (Objects.isNull(receiptManage)) {
                    logger.error("{}小区未设置收据模板！", order.getCommunityNo());
                    return Result.error(0, "请先去设置或开启收据模板！");
                }
            }catch (Exception e){
                return Result.error(0, "票据模板设置不合理，同一个小区只能配置一个模板！");
            }

            if(!order.getOrderStatus().equals(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS)){
                logger.error("缴费订单orderNo:{} 还未缴费，不能生成收据！",order.getOrderNo());
                return Result.error(0,  "未缴费不能生成收据！");
            }
            //3、查询账单数据
            Map<String,Object> mapParam = new LinkedHashMap<>();
            mapParam.put("company", receiptManage.getReceiptTitleName());
            mapParam.put("community",order.getCommunityName());

            FileOutputStream outputFileStream = null;
            try {
                String realName = order.getChargeName();
                if(StringUtil.isEmpty(realName)){
                    realName = getOwnerName(token.getCompanyNo(),order.getHouseBillNo());
                }
                //房东姓名
                mapParam.put("realName",realName);
                // 显示： 12栋-1801
                mapParam.put("houseInfo",order.getBillAddress());
                mapParam.put("datePay",order.getPayTime());
                String receiptNo = PdfTableUtil.generateNumber("NO.SJ");
                mapParam.put("receiptNO",receiptNo);
                //上传的签章图片
                String fileImg = fileUrlConfig.getFile(receiptManage.getSealImgId());
                mapParam.put("sealFile",fileImg);
                mapParam.put("type","receipt");
                //应付金额
                mapParam.put("totalAmount",order.getPaymentAmount());
                mapParam.put("content",order.getOrderYearMonth());
                mapParam.put("payMethod",order.getPayMethod().getDesc());

                //查询账单项
                List<ChargeBillItems> billItems = jdbcSession.findArray(ChargeBillItems.class)
                        .eq("houseBillNo", order.getHouseBillNo())
                        .eq("billStatus",ChargeBillStatusEnum.BILL_PAID_FINISH).exe();
                mapParam.put("dataList",billItems);

                //4、生成PDF文件
                PdfUtil pdfUtil = new PdfUtil();
                byte[] pdf = pdfUtil.execute(mapParam);
                String pdfName = receiptNo+".pdf";
                File file = new File(pdfName);
                outputFileStream = new FileOutputStream(file);
                outputFileStream.write(pdf);
                //保存收据单数据
                ReceiptOrders receipt =  Pool.newInstance(ReceiptOrders.class);
                receipt.setReceiptNo(receiptNo); //生成自定义编号
                receipt.setHouseBillNo(order.getHouseBillNo());
                receipt.setPayOrderNo(order.getOrderNo());
                JSONObject jsonObject =  fileUrlConfig.sendFile(file, http->{});
                String fileId = jsonObject.getJSONObject("data").getString("id");
                receipt.setFileId(fileId);
                receipt.setHouseInfo(order.getBillAddress());
                receipt.setCommunityNo(order.getCommunityNo());
                receipt.setCommunityName(order.getCommunityName());
                //receipt.setBatchPayOrderNo(receiptOrder.getChargeRecordId());
                receipt.setDepartmentNo(order.getDepartmentNo());
                receipt.setDepartmentName(order.getDepartmentName());
                receipt.setDepartmentNos(order.getDepartmentNos());
                receipt.setEnableStat(EnableStateEnum.UNUSED);
                boolean isSuccess =  jdbcSession.insert(receipt)==1;
                //文件上传成功后自动删除
                if (file.exists() && file.isFile() && file.delete()) {
                    logger.info("{}本地文件已经删除!",pdfName);
                }
                if(isSuccess){
                    //将之前的收据全部置为失效
                    List<ReceiptOrders> receiptList = receiptOrderService.findListByHouseNo(order.getHouseBillNo());
                    List<ReceiptOrders> oldReceipt = receiptList.stream().filter(r -> !r.getReceiptNo().equals(receiptNo)).collect(Collectors.toList());
                    oldReceipt.forEach(o->o.setEnableStat(EnableStateEnum.ENABLE));
                    jdbcSession.updateById(oldReceipt);
                }
                return isSuccess;
            } catch (Exception e) {
                logger.error("生成PDF异常",e);
                return Result.error(0,"生成PDF异常！");
            } finally {
                if(null != outputFileStream){
                    try {
                        outputFileStream.close();
                    } catch (IOException e) {
                        logger.error("生成收据功能异常，关闭outputFileStream流时发生IO异常");
                        return Result.error(0,"系统异常，请联系管理员");
                    }
                }
            }
        }

       return Result.success();
    }


    /**
     * 手动生成缴费PDF
     * @param jsonObject
     * @return
     * @throws Exception
     */
    @Override
    public Object manualPaySave(JSONObject jsonObject){

        JSONArray idList = jsonObject.getJSONArray("idList");
        if(Objects.isEmpty(idList)){
            return Result.error(0, "需要生成的账单ID列表不能为空");
        }
        for (Object billNo : idList) {

            //1、根据账单ID查询账单
            ChargeBillHouse bill = jdbcSession.findOne(ChargeBillHouse.class)
                    .eq("deleted", false)
                    .eq("houseBillNo",billNo.toString())
                    .exe();
            if(Objects.isNull(bill)){
                return Result.error(0, "生成缴费单失败！没有找到id:"+billNo +" 相关的账单");
            }
            if(ChargeBillStatusEnum.BILL_PAID_CLOSE.equals(bill.getBillStatus())){
                return Result.error(0, "生成缴费单失败！id："+billNo +"账单已作废");
            }


            String communityNo = bill.getCommunityNo();
            logger.info("手动生成缴费单PDF文件！小区编号：{}",communityNo);
            PayBillManages receiptManage;
            try {
                //1、查询电子签章,判断是否有配置收据模板及公章
                receiptManage = jdbcSession.findOne(PayBillManages.class)
                        .like("communityList", communityNo)
                        .eq("status", true).exe();

                if (Objects.isNull(receiptManage)) {
                    logger.error("{}小区未设置缴费单模板！", communityNo);
                    return Result.error(0, "请先去设置或开启账单["+billNo+"]的缴费单模板！");
                }
            }catch (Exception e){
                return Result.error(0, "账单id:"+billNo+" 缴费单模板设置不合理，同一个小区只能配置一个模板！");
            }

            //3、查询账单数据
            Map<String,Object> mapParam = new LinkedHashMap<>();
            mapParam.put("company", receiptManage.getTitleName());
            mapParam.put("community",bill.getCommunityName());
            mapParam.put("realName",bill.getChargeName());
            // 显示： 12栋-1801
            mapParam.put("houseInfo",bill.getBillAddress());
            mapParam.put("datePay", Java8TimeUtils.dateShort());
            String receiptNo = PdfTableUtil.generateNumber("NO.");
            mapParam.put("receiptNO",receiptNo);
            //上传的签章图片
            String fileImg = fileUrlConfig.getFile(receiptManage.getSealImgId());
            mapParam.put("sealFile",fileImg);
            mapParam.put("totalAmount",bill.getBillAmountUnPaid());
            mapParam.put("content",bill.getBillYearMonth());
            //type : 收据：receipt,缴费单：payBill
            mapParam.put("type","payBill");
            mapParam.put("remark",receiptManage.getRemark());

            //查询账单项
            List<ChargeBillItems> billItems = jdbcSession.findArray(ChargeBillItems.class)
                    .eq("deleted",false)
                    .eq("houseBillNo", bill.getHouseBillNo())
                    .eq("billStatus",ChargeBillStatusEnum.BILL_WAIT_PAID)
                    .exe();
            mapParam.put("dataList",billItems);
            //4、生成PDF文件
            FileOutputStream outputFileStream = null;
            try {
                PdfUtil pdfUtil = new PdfUtil();
                byte[] pdf = pdfUtil.execute(mapParam);
                String pdfName = receiptNo+".pdf";
                File file = new File(pdfName);
                outputFileStream = new FileOutputStream(file);
                outputFileStream.write(pdf);

                //保存收据单数据
                PayBillRecords receipt =  Pool.newInstance(PayBillRecords.class);
                receipt.setPayBillNo(receiptNo); //生成自定义编号
                receipt.setPayOrderNo(bill.getId());
                receipt.setHouseBillNo(bill.getHouseBillNo());
                receipt.setHouseNo(bill.getHouseNo());
                JSONObject json =  fileUrlConfig.sendFile(file, http->{ });
                String fileId = json.getJSONObject("data").getString("id");
                receipt.setFileId(fileId);
                receipt.setHouseInfo(bill.getBillAddress());
                receipt.setCommunityNo(communityNo);
                receipt.setDepartmentName(bill.getDepartmentName());
                receipt.setDepartmentNo(bill.getDepartmentNo());
                receipt.setDepartmentNos(bill.getDepartmentNos());
                receipt.setChargeName(bill.getChargeName());
                receipt.setUserNo(bill.getUserNo());
                receipt.setResidentsType(bill.getResidentsType());
                receipt.setEnableStat(EnableStateEnum.UNUSED);
                boolean isSuccess = jdbcSession.insert(receipt)==1;
                //文件上传成功后自动删除
                if (file.exists() && file.isFile() && file.delete()) {
                    logger.info("{}本地文件已经删除!",pdfName);
                }
                if(isSuccess){
                    //将之前的收据全部置为失效
                    List<PayBillRecords> payBillList = payManagesService.findBIllRecordListByHouseNo(bill.getHouseBillNo());
                    List<PayBillRecords> oldPayBill = payBillList.stream().filter(b -> !b.getPayBillNo().equals(receiptNo)).collect(Collectors.toList());
                    oldPayBill.forEach(o->o.setEnableStat(EnableStateEnum.ENABLE));
                    jdbcSession.updateById(oldPayBill);
                }
            } catch (Exception e) {
                logger.error("生成PDF异常",e);
                return Result.error(0,"账单{} 生成PDF异常！",billNo.toString());
            } finally {
                if(null != outputFileStream){
                    try {
                        outputFileStream.close();
                    } catch (IOException e) {
                        logger.error("生成缴费单功能异常，关闭outputFileStream流时发生IO异常");
                        return Result.error(0,"系统异常，请联系管理员");
                    }
                }
            }
        }
        return true;
    }


}
